package gui.mainFrame.testConditionViewer.branchTable;

import gui.GUIController;
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
import testGenerator.Controller;
import testGenerator.testMethodModel.TestPath;
import testGenerator.testMethodModel.TestCondition;
import testGenerator.testMethodModel.AutoJUnitMethod;

/**
 * Provides a table model for the table
 * @author William Whitney
 */
public class BranchTableModel extends AbstractTableModel
{
    private static final long serialVersionUID = 1L;

    private final GUIController guiController;
    private final Controller controller;

    /**
     * Default constructor.
     * @param guiController
     * @param control
     */
    public BranchTableModel(GUIController guiController, Controller control)
    {
        this.controller = control;
        this.guiController = guiController;
    }

    /**
     * Returns column name.
     * @param column
     * @return
     */
    @Override
    public String getColumnName(int column)
    {
        if (column == 0)
        {
            return "Num";
        }
        else if (column > getLargestNumberOfTestConditons())
        {
            return "Status";
        }
        else
        {
            return "Cond: " + column;
        }
    }

    /**
     * Gets value at row, col index.
     * @param rowIndex
     * @param columnIndex
     * @return
     */
    @Override
    public Object getValueAt(int rowIndex, int columnIndex)
    {
        AutoJUnitMethod method = this.controller.getCurrMethod();
        ArrayList<TestPath> branches = method.testBranches;
        TestPath currBranch = branches.get(rowIndex);
        ArrayList<TestCondition> testConditions = currBranch.conditions;

        if (columnIndex == 0)
        {
            return rowIndex + 1;
        }
        else if (columnIndex == getLargestNumberOfTestConditons() + 1)
        {
            return currBranch.getStatus(method);
        }
        //Case where we have found a branch smaller than largest
        else if (columnIndex >= testConditions.size() + 1)
        {
            return " ------ ";
        }
        //Output condition
        else
        {
            return currBranch.conditions.get(columnIndex - 1).getCondition();
        }
    }

    /**
     * Returns number of rows.
     * @return
     */
    @Override
    public int getRowCount()
    {
        AutoJUnitMethod method = this.controller.getCurrMethod();
        ArrayList<TestPath> branches = method.testBranches;
        return branches.size();
    }

    /**
     * Returns number of columns.
     * @return
     */
    @Override
    public int getColumnCount()
    {
        return getLargestNumberOfTestConditons() + 2;
    }

    /**
     * Determines that number of conditions in the largest test branch.
     * @return
     */
    private int getLargestNumberOfTestConditons()
    {
        int max = 0;

        //TODO poor performance code
        for (TestPath branch : this.controller.getCurrMethod().testBranches)
        {
            if (branch.conditions.size() > max)
            {
                max = branch.conditions.size();
            }
        }
        return max;
    }

    public TestPath getBranchAtRow(int selectedRow)
    {
        return controller.getCurrMethod().testBranches.get(selectedRow);
    }

    public void duplicateBranchAtRow(int selectedRow)
    {
        TestPath currBranch = controller.getCurrMethod().testBranches.get(selectedRow);

        try
        {
            controller.getCurrMethod().testBranches.add((TestPath) currBranch.clone());
            this.fireTableStructureChanged();
        }
        catch (Exception error)
        {
            error.printStackTrace();
        }
    }

    public void deleteBranchRow(int selectedRow)
    {
        controller.getCurrMethod().testBranches.remove(selectedRow);
        this.fireTableStructureChanged();
    }

    void addBranch(TestPath newBranch)
    {
        controller.getCurrMethod().testBranches.add(newBranch);
        this.fireTableStructureChanged();
    }
}
